package org.tloss.web.editor;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.tloss.web.editor.database.editors.jdbc.Table;
import org.tloss.web.editor.model.Sql;
import org.tloss.web.editor.utils.Constants;

public class Utils {
	
	public static IFolder createFolder(IProject project, String path,
			IProgressMonitor monitor) {
		IFolder folder = project.getFolder(path);
		if (!folder.exists()) {
			try {
				folder.create(true, true, monitor);
			} catch (CoreException e) {
				Utils.logError("Can't create template folder", e);
				return null;
			}
		}
		return folder;
	}
	public static IFile createEmptyFile(IFolder folder, String fileName,
			IProgressMonitor monitor) {
		IFile file = folder.getFile(fileName);
		if (!file.exists()) {
			ByteArrayInputStream input = new ByteArrayInputStream(
					Constants.EMPTY_BYTES);
			try {
				file.create(input, true, monitor);
			} catch (CoreException e) {
				Utils.logError("Can't create template file", e);
				return null;
			}
		}
		return file;
	}
	public static IFile createFile(IFolder folder, String fileName,
			IProgressMonitor monitor,InputStream input) {
		IFile file = folder.getFile(fileName);
		if (!file.exists()) {
			try {
				file.create(input, true, monitor);
			} catch (CoreException e) {
				Utils.logError("Can't create template file", e);
				return null;
			}
		}
		return file;
	}
	
	public static IResource getCurrentResource() {
		IResource project = null;
		IWorkbench iworkbench = PlatformUI.getWorkbench();
		if (iworkbench != null) {
			IWorkbenchWindow iworkbenchwindow = iworkbench
					.getActiveWorkbenchWindow();
			if (iworkbenchwindow != null) {

				IStructuredSelection selection = (IStructuredSelection) iworkbenchwindow
						.getSelectionService().getSelection();
				Object firstElement = selection.getFirstElement();
				IResource file = (IResource) Platform.getAdapterManager()
						.getAdapter(firstElement, IResource.class);
				if (file == null) {
					if (firstElement instanceof IAdaptable) {
						file = (IFile) ((IAdaptable) firstElement)
								.getAdapter(IResource.class);
					}
				}
				if (file != null) {
					project = file;
				}
			}
		}
		return project;
	}

	public static IProject getCurrentProject() {

		IProject project = null;
		IWorkbench iworkbench = PlatformUI.getWorkbench();
		if (iworkbench != null) {
			IWorkbenchWindow iworkbenchwindow = iworkbench
					.getActiveWorkbenchWindow();
			if (iworkbenchwindow != null) {
				IWorkbenchPage iworkbenchpage = iworkbenchwindow
						.getActivePage();
				if (iworkbenchpage != null) {
					IEditorPart ieditorpart = iworkbenchpage.getActiveEditor();
					if (ieditorpart != null) {
						IResource resource = extractResource(ieditorpart);
						if (resource != null) {
							project = resource.getProject();
						}
					}
				}
				if (project == null) {
					IStructuredSelection selection = (IStructuredSelection) iworkbenchwindow
							.getSelectionService().getSelection();
					Object firstElement = selection.getFirstElement();
					if (firstElement instanceof IAdaptable) {
						project = (IProject) ((IAdaptable) firstElement)
								.getAdapter(IProject.class);
					}
				}

			}
		}
		return project;
	}

	private static Properties config = new Properties();

	public static String getProperty(IProject iProject, String name,
			String defaultValue) {
		if (iProject != null) {
			IFile file = iProject.getFile(Constants.CONFIG_FILE);
			if (file != null && file.exists()) {
				InputStream inputStream = null;
				try {
					inputStream = file.getContents();
					config.load(inputStream);
					inputStream.close();
					inputStream = null;
					return config.getProperty(name, defaultValue);
				} catch (CoreException e) {
					logError("Can't load Properties", e);
				} catch (IOException e) {
					logError("Can't load Properties", e);
				} finally {
					if (inputStream != null) {
						try {
							inputStream.close();
						} catch (IOException e) {
							logError("Can't load Properties", e);
						}
					}
				}
			}
		}
		return defaultValue;
	}
	public static Properties getProperties(IProject iProject) {
		Properties config =  new Properties();
		if (iProject != null) {
			IFile file = iProject.getFile(Constants.CONFIG_FILE);
			if (file != null && file.exists()) {
				InputStream inputStream = null;
				try {
					inputStream = file.getContents();
					config.load(inputStream);
					inputStream.close();
					inputStream = null;
					
				} catch (CoreException e) {
					logError("Can't load Properties", e);
				} catch (IOException e) {
					logError("Can't load Properties", e);
				} finally {
					if (inputStream != null) {
						try {
							inputStream.close();
						} catch (IOException e) {
							logError("Can't load Properties", e);
						}
					}
				}
			}
		}
		return config;
	}

	public static IResource extractResource(IEditorPart editor) {
		IEditorInput input = editor.getEditorInput();
		if (!(input instanceof IFileEditorInput))
			return null;
		return ((IFileEditorInput) input).getFile();
	}

	public static void logInfo(String message) {
		log(IStatus.INFO, IStatus.OK, message, null);
	}

	public static void logError(Throwable exception) {
		logError("Unexpected Exception", exception);
	}

	public static void logError(String message, Throwable exception) {
		log(IStatus.ERROR, IStatus.OK, message, exception);
	}

	public static void log(int severity, int code, String message,
			Throwable exception) {
		log(createStatus(severity, code, message, exception));
	}

	public static IStatus createStatus(int severity, int code, String message,
			Throwable exception) {
		return new Status(severity, Activator.PLUGIN_ID, code, message,
				exception);
	}

	public static void log(IStatus status) {
		Activator.getDefault().getLog().log(status);
	}

	public static Table loadEnity(IProject project, String tableName) {
		Table table = null;
		IFolder folder = project.getFolder(Constants.ENTITY_FOLDER);
		if (folder.exists()) {
			IFile file = folder.getFile(tableName + "." + Constants.ENTITY_EXT);
			if (file.exists()) {
				JAXBContext context;
				InputStream inputStream = null;
				try {
					inputStream = file.getContents();
					if (inputStream.available() > 0) {
						context = JAXBContext.newInstance(Table.class);
						Unmarshaller marshaller = context.createUnmarshaller();
						table = (Table) marshaller.unmarshal(inputStream);
					}
				} catch (CoreException e) {
					Utils.logError("Can't load entity by name: " + tableName, e);
				} catch (JAXBException e) {
					Utils.logError("Can't load entity by name: " + tableName, e);
				} catch (IOException e) {
					Utils.logError("Can't load entity by name: " + tableName, e);
				} finally {
					try {
						if (inputStream != null) {
							inputStream.close();
						}
					} catch (IOException e) {
						Utils.logError("Can't close inputstream: " + tableName,
								e);
					}
				}
			}
		}
		return table;
	}

	public static Sql loadSql(String resource) {
		IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace()
				.getRoot();
		IFile iFile = myWorkspaceRoot.getFile(new Path(resource));
		JAXBContext context;
		InputStream inputStream = null;
		Unmarshaller marshaller;
		if (iFile != null) {
			try {
				context = JAXBContext.newInstance(Sql.class);
				marshaller = context.createUnmarshaller();
				inputStream = iFile.getContents();
				if (inputStream.available() > 0) {
					return (Sql) marshaller.unmarshal(inputStream);
				}
			} catch (JAXBException e) {
				Utils.logError("Can't load sql: " + resource, e);
			} catch (CoreException e) {
				Utils.logError("Can't load sql: " + resource, e);
			} catch (IOException e) {
				Utils.logError("Can't load sql: " + resource, e);
			}

		}
		return null;
	}

	public static List<Object> loadEnities(IProject project) {
		List<Object> tables = new ArrayList<Object>();
		Table table = null;
		IFolder folder = project.getFolder(Constants.ENTITY_FOLDER);
		if (folder.exists()) {
			IResource[] resources;
			try {
				resources = folder.members();
				if (resources != null) {
					for (int i = 0; i < resources.length; i++) {
						table = null;
						if (resources[i].getType() == IResource.FILE) {
							IFile file = (IFile) resources[i];
							if (file.exists()) {
								JAXBContext context;
								InputStream inputStream = null;
								try {
									inputStream = file.getContents();
									if (inputStream.available() > 0) {
										context = JAXBContext
												.newInstance(Table.class);
										Unmarshaller marshaller = context
												.createUnmarshaller();
										table = (Table) marshaller
												.unmarshal(inputStream);
									}
								} catch (CoreException e) {
									Utils.logError(
											"Can't load entity by name: "
													+ file.getName(), e);
								} catch (JAXBException e) {
									Utils.logError(
											"Can't load entity by name: "
													+ file.getName(), e);
								} catch (IOException e) {
									Utils.logError(
											"Can't load entity by name: "
													+ file.getName(), e);
								} finally {
									try {
										if (inputStream != null) {
											inputStream.close();
										}
									} catch (IOException e) {
										Utils.logError(
												"Can't close inputstream: "
														+ file.getName(), e);
									}
								}
							}
						}
						if (table != null) {
							tables.add(table);
						}
					}
				}
			} catch (CoreException e1) {
				Utils.logError("error read resource", e1);
			}

		}
		return tables;
	}
}
